﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Serialization;

namespace Fuse8.ContentManagementFramework.Web.MvcPowered.Components.Editors
{
    [Serializable]
    [XmlType("editorSettings")]
    public class EditorSetting
    {
        [XmlArray("tools")]
        [XmlArrayItem("tool")]
        public EditorTool[] Tools { get; set; }

        [XmlArray("fileBrowser")]
        [XmlArrayItem("add")]
        public BrowseSetting[] BrowseSettings { get; set; }

        [XmlArray("cssFiles")]
        [XmlArrayItem("add")]
        public string[] CustomCssFiles { get; set; }

        internal void MergeWith(EditorSetting customSettings)
        {
            MergeTools(customSettings);
            MergeBrowseSettings(customSettings);
            MergeCssFiles(customSettings);
        }

        private void MergeCssFiles(EditorSetting customSettings)
        {
            var ownSetting = (CustomCssFiles ?? new string[0]);
            if (customSettings.CustomCssFiles != null)
            {
                CustomCssFiles = ownSetting.Concat(customSettings.CustomCssFiles).ToArray();
            }
        }

        private void MergeBrowseSettings(EditorSetting customSettings)
        {
            if (customSettings.BrowseSettings != null && customSettings.BrowseSettings.Length > 0)
            {
                var settings = BrowseSettings.Select(editorTool => (customSettings.BrowseSettings.FirstOrDefault(p => p.Name == editorTool.Name) ?? editorTool)).ToList();
                BrowseSettings = settings.ToArray();
            }
        }

        private void MergeTools(EditorSetting customSettings)
        {
            if (customSettings.Tools != null && customSettings.Tools.Length > 0)
            {
                var tools = Tools.Select(editorTool => (customSettings.Tools.FirstOrDefault(p => Math.Abs(p.Index - editorTool.Index) < 0.0001) ?? editorTool)).ToList();
                foreach (var tool in customSettings.Tools)
                {
                    if (!tools.Any(p => Math.Abs(p.Index - tool.Index) < 0.0001))
                    {
                        tools.Add(tool);
                    }
                }

                Tools = tools.OrderBy(p => p.Index).ToArray();
            }
        }
    }

    [Serializable]
    public class EditorTool
    {
        [XmlAttribute("name")]
        public string Name { get; set; }
        
        [XmlAttribute("type")]
        public EditorToolType Type { get; set; }
        
        [XmlArray("attributes")]
        [XmlArrayItem("add")]
        public EditorSettingItem[] Attributes { get; set; }

        [XmlArray("styles")]
        [XmlArrayItem("add")]
        public EditorSettingItem[] Styles { get; set; }

        [XmlArray("snippets")]
        [XmlArrayItem("add")]
        public EditorSettingItem[] Snippets { get; set; }

        [XmlAttribute("index")]
        public double Index { get; set; }
    }

    [Serializable]
    public class EditorSettingItem
    {
        [XmlAttribute("name")]
        public string Name { get; set; }

        [XmlAttribute("value")]
        public string Value { get; set; }

        [XmlText]
        public string Text { get; set; }
    }

    [Serializable]
    public class BrowseSetting
    {
        [XmlAttribute("name")]
        public string Name { get; set; }

        [XmlAttribute("controller")]
        public string Controller { get; set; }

        [XmlAttribute("action")]
        public string Action { get; set; }
    }

    [Serializable]
    public enum EditorToolType
    {
        Standard,
        Styles,
        Snippets,
        Custom
    }
}